<?php
require_once (dirname(__FILE__) . "/HttpTalk.php"); // automatically include httptalk class
require_once (dirname(__FILE__) . "/../server/ServerDao.php"); // automatically include serverdb class
require_once (dirname(__FILE__) . "/../server/ProxyDao.php"); // automatically include proxydb class
?>
<?php

// error code
require_once (dirname(__FILE__) . "/../../proxy_errorcode.php");
// timeout settings
define("WFPROXY_TIMEOUT", 30);
define("WFPROXY_TIMEOUT_CONNECT", 10);
?>
<?php

require_once (dirname(__FILE__) . "/../../debug.php");
if(!defined('WF_ERR_MSG')){
    define('WF_ERR_MSG','Error');
}
?>
<?php

/*
 * All proxy module must inherit from this base class
 * Created: 200903 (TT Tsai)
 */
abstract class ABaseProxy
{
    //
    protected $cgiArgs; // all cgi parameters are stored in this associative array
    protected $errCode; // for error checking
    protected $errMessage; // for error checking (Note: only for debug, not for UI)
    protected $httpObj; // easy http communication object
    protected $serverid;
    protected $TargetServer; //GUID of server
    protected $serverInfo; // use this object to retrieve server information
    protected $proxyid;
    protected $proxyInfo; // use this object to retrieve proxy information
    protected $userid;
    protected $session_info; // use this to store cookie/auth information and speed up your login
    // It is an object. You can store everything you want.
    // The variable will be load when you create the object.
    // And it will be saved to $_SESSION automatically in __destroctor().
    // Force extending class to define these methods
    /*
     * proxy_init()
     * Input: void
     * Return: TRUE or FALSE
     * Description:
     *    1. Proxy starts here.
     *    2. You should check things like:
     *        - Check all cgi parameters.
     *        - Read server information and validate.
     *        - ...
     *    3. If anything error, set $this->errCode and $this->errMessage and return FALSE.
     */
    abstract protected function proxy_init();
    /*
     * proxy_exec()
     * Input: void
     * Return: TRUE or FALSE
     * Description:
     *    1. Proxy connects to server,sends request and get responses.
     *    2. And report any 'connecting' error. (set $this->errCode and $this->errMessage and return FALSE)
     */
    abstract protected function proxy_exec();
    /*
     * proxy_output()
     * Input: void
     * Return: TRUE or FALSE
     * Description:
     *    1. Just output data when successful and return TRUE.
     *    2. If anything error, set $this->errCode and $this->errMessage and return FALSE.
     */
    abstract protected function proxy_output();
    // Constructor
    public function __construct($args, $dbconfig){
        $this->cgiArgs = $args;
        $this->errCode = WF_PROXY_ERR_NONE;
        $this->errMessage = "";
        $this->httpObj = new WFHttpTalk();
        // http default settings
        $this->httpObj->setTimeout_connect(WFPROXY_TIMEOUT_CONNECT);
        $this->httpObj->setTimeout(WFPROXY_TIMEOUT);
        // check userid (for permission checking)
        if(isset($_SESSION['uid'])){
            $this->userid = $_SESSION['uid'];
        }else{
            $this->errCode = WF_PROXY_ERR_INIT_INVALID_USERID;
            $this->errMessage = WF_PROXY_ERR_INIT_INVALID_USERID_MSG;
            return;
        }
        // serverInfo
        if(isset($args["serverid"]) && $args["serverid"]){
            $this->serverid = $args["serverid"];
            // new server db
            $serverdb = new WFServerDao($dbconfig, $this->userid);
            if($serverdb->isFailed()){
                $this->errCode = WF_PROXY_ERR_INIT_DBERR;
                //@todo move WF_ERR_MSG to $WGF_ROOT/response.php
                $this->errMessage = WF_ERR_MSG.": ". $serverdb->getErrMessage();
                return;
            }
            $serverIds = explode(',', str_replace(' ', '', $args["serverid"]));
            // get server info
            $sinfo = array();
            $total = count($serverIds);
            for($i = 0; $i < $total; ++$i){
                $sinfo[] = $serverdb->getinfo($serverIds[$i]);
                if($serverdb->isFailed()){
                    $this->errCode = WF_PROXY_ERR_INIT_DBERR;
                    //@todo move WF_ERR_MSG to $WGF_ROOT/response.php
                    $this->errMessage = WF_ERR_MSG.": ". $serverdb->getErrMessage();
                    return;
                }
            }
            $this->serverInfo = ($total > 1) ? $sinfo : $sinfo[0];
        }
		else
		{
            $this->serverInfo = null;
        }
		
		
        if(isset($this->serverInfo["proxy_enable"]) && $this->serverInfo["proxy_enable"] == 1){
            $this->proxyid = $this->serverInfo["proxy_id"];
        }else if(isset($total) && $total > 1){
            foreach($this->serverInfo as $server){
                if(! isset($server['proxy_enable']) || $server['proxy_enable'] != 1){
                    continue;
                }
                $this->proxyid = $server['proxy_id'];
                break;
            }
        }
        
		if($this->proxyid)
		{
            // new proxy db
            $proxydb = new WFProxyDao($dbconfig, $this->userid);
            if($proxydb->isFailed()){
                $this->errCode = WF_PROXY_ERR_INIT_DBERR;
                //@todo move WF_ERR_MSG to $WGF_ROOT/response.php
                $this->errMessage = WF_ERR_MSG.": ". $proxydb->getErrMessage();
                return;
            }
            // get proxy info
            $this->proxyInfo = $proxydb->getinfo($this->proxyid);
            if($proxydb->isFailed()){
                $this->errCode = WF_PROXY_ERR_INIT_DBERR;
                //@todo move WF_ERR_MSG to $WGF_ROOT/response.php
                $this->errMessage = WF_ERR_MSG.": ". $proxydb->getErrMessage();
                return;
            }
        }
		
        if(isset($args["serverid"]) && $total === 1 && $args['serverid'] > 1 && $this->serverInfo){
            // set server info to httpObj
			mydebug_log("[BASE Proxy] set_server_info -->");
            $this->set_server_info();
        }
		elseif(isset($args["ApplyToServer"]))
		{
            // set server info to httpObj
			mydebug_log("[BASE Proxy] set_server_info_task -->");
            $this->set_server_info_task();
			$this->set_server_info();
        }
		
        // load session_info
        $this->read_sinfo();
        // do init
        $this->proxy_init();
    }
    // Destructor
    public function __destruct(){
        $this->save_sinfo();
    }
    /*
     * Methods for saving session info
     */
    public function save_sinfo(){
        session_start();
        if(isset($_SESSION["session_info"])){
            $new_sessioninfo = $_SESSION["session_info"];
            if($this->session_info){
                $_SESSION["session_info"] = array_merge($new_sessioninfo, $this->session_info);
            }else{
                $_SESSION["session_info"] = $new_sessioninfo;
            }
        }else{
            $_SESSION["session_info"] = $this->session_info;
        }
        session_write_close();
    }
    public function read_sinfo(){
        if(isset($_SESSION["session_info"])){
            $this->session_info = $_SESSION["session_info"];
        }else{
            $this->session_info = null;
        }
    }
    /*
     * Optional methods
     * You can use these functions to save your time.
     */
    // set $serverInfo to $httpObj
    protected function set_server_info(){
        // server info
        $this->httpObj->setServer($this->serverInfo['host']);
        $this->httpObj->setPort($this->serverInfo['port']);
        if($this->serverInfo['protocol'] == 'https'){
            $this->httpObj->setProtocol_HTTPS();
        }else{
            $this->httpObj->setProtocol_HTTP();
        }
        // proxy info
        if(isset($this->serverInfo['proxy_enable']) && ($this->serverInfo['proxy_enable'] == 1)){
            //var_dump($this->proxyInfo);
            $this->httpObj->setProxyServer($this->proxyInfo['host']);
            $this->httpObj->setProxyPort($this->proxyInfo['port']);
            if($this->proxyInfo['auth'] == 1)
                $this->httpObj->setProxyAuthInfo($this->proxyInfo['username'], $this->proxyInfo['password']);
            if($this->proxyInfo['type'] == 'http')
                $this->httpObj->setProxyType_HTTP();
            elseif($this->proxyInfo['type'] == 'sock4')
                $this->httpObj->setProxyType_SOCKS4();
            elseif($this->proxyInfo['type'] == 'sock5')
                $this->httpObj->setProxyType_SOCKS5();
        }
    }
    /*
     * Optional methods
     * You can use these functions to save your time.
     */
    // set $serverInfo to $httpObj
    protected function set_server_info_task()
	{
		// server information		
		$this->serverInfo['host'] = $this->cgiArgs["TargetServerIP"];
		$this->serverInfo['port'] = $this->cgiArgs["TargetPort"];
		$this->serverInfo['protocol'] = $this->cgiArgs["TargetProtocol"];
		$this->serverInfo['proxy_enable'] = $this->cgiArgs["ApplyProxy"];
		$this->serverInfo['password'] = $this->cgiArgs["Password"];
		$this->serverInfo['username'] = $this->cgiArgs["ID"];
                $this->serverInfo['customFields'] = $this->cgiArgs["Others"];

		// proxy information
		$this->proxyInfo['host'] = $this->cgiArgs["ProxyServer"];
		$this->proxyInfo['port'] = $this->cgiArgs["ProxyPort"];
		$this->proxyInfo['auth'] = $this->cgiArgs["ProxyNeedAuth"];
		$this->proxyInfo['username'] = $this->cgiArgs["ProxyUserID"];
		$this->proxyInfo['password'] = $this->cgiArgs["ProxyPassword"];
		$this->proxyInfo['type'] = $this->cgiArgs["ProxyType"];
    }
	
    // Error handling methods
    public function isFailed(){
        if($this->errCode != WF_PROXY_ERR_NONE){
            return TRUE;
        }
        return FALSE;
    }
    public function getErrCode(){
        return $this->errCode;
    }
    public function getErrMessage(){
        return $this->errMessage;
    }
}
?>
